﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Toolbox Collapsible Panel Control Class
 *      Provides a composite collapsible panel control for containing toolbox items.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Provides a composite collapsible panel control for containing toolbox items.
    /// </summary>
    [ToolboxItem(false)]
    public partial class ToolboxCollapsiblePanel : ToolboxControlBase 
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        /// <summary>
        /// Occurs when the panel is collapsed.
        /// </summary>
        public event EventHandler Collapsed;
        /// <summary>
        /// Occurs when the panel is expanded.
        /// </summary>
        public event EventHandler Expanded;
        /// <summary>
        /// Occurs when the panel is collapsed or expanded.
        /// </summary>
        public event EventHandler ConditionChanged;
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Height of the control when expanded.
        /// </summary>
        private int _expandedHeight;
        /// <summary>
        /// Event re-entry prevention flag.
        /// </summary>
        private bool _processing;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public ToolboxCollapsiblePanel()
            : base()
        {
            InitializeComponent();
            PanelTitleControl.TextOffset = new Point(15, 1);
            base.Height = 16;
            _expandedHeight = 16;
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
            }
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the height of the control.
        /// </summary>
        /// <value></value>
        /// <returns>The height of the control in pixels.</returns>
        /// <PermissionSet>
        /// 	<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// 	<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/>
        /// 	<IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// </PermissionSet>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new int Height
        {
            get { return base.Height; }
            set
            {
                if (PanelTitleControl.VisualState == CollapsiblePanelState.Collapsed)
                {
                    base.Height = 16;
                    _expandedHeight = value;
                }
                else
                {
                    _expandedHeight = value;
                    if (_expandedHeight < 16)
                        _expandedHeight = 16;
                    base.Height = _expandedHeight;
                }
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the visual state of the control.
        /// </summary>
        /// <value>
        /// An <see cref="CollapsiblePanelState"/> enumerated value indicating whether teh panel is collapsed or 
        /// expanded.
        /// </value>
        [Browsable(true), DefaultValue(0), Description("Expands or collapses the control.")]
        public CollapsiblePanelState VisualState
        {
            get { return PanelTitleControl.VisualState; }
            set
            {
                PanelTitleControl.VisualState = value;
            }
        }
        /// <summary>
        /// Gets or sets the text of the control.
        /// </summary>
        /// <value>The text associated with this control.</value>
        [Browsable(true), DefaultValue(""), Description("Text to be displayed."),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get
            {
                return PanelTitleControl.Text;
            }
            set
            {
                PanelTitleControl.Text = value;
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Creates and assigns the event handlers for the items contained within the control.
        /// </summary>
        protected override void AssignEventHandlers()
        {
            PanelTitleControl.Expanded +=new EventHandler(HandleTitleExpand);
            PanelTitleControl.Collapsed +=new EventHandler(HandleTitleCollapse);
            PanelTitleControl.ConditionChanged +=new EventHandler(HandleTitleConditionChange);
            PanelTitleControl.RightClick +=new EventHandler(HandleControlRightClick);
            ContainerPanel.RightClick +=new EventHandler(HandleControlRightClick);
        }
        /// <summary>
        /// Removes the event handlers for the items contained within the control.
        /// </summary>
        protected override void RemoveEventHandlers()
        {
            PanelTitleControl.Expanded -= new EventHandler(HandleTitleExpand);
            PanelTitleControl.Collapsed -= new EventHandler(HandleTitleCollapse);
            PanelTitleControl.ConditionChanged -= new EventHandler(HandleTitleConditionChange);
            PanelTitleControl.RightClick -= new EventHandler(HandleControlRightClick);
            ContainerPanel.RightClick -= new EventHandler(HandleControlRightClick);
        }
        /// <summary>
        /// Suggests the correct height value for the control.
        /// </summary>
        /// <returns>
        /// The suggested control height, in pixels.
        /// </returns>
        protected override int SuggestHeight()
        {
            return PanelTitleControl.Height + (ContainerPanel.Controls.Count * 15);
        }
        /// <summary>
        /// Raises the <see cref="E:ConditionChanged"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void OnConditionChanged(EventArgs e)
        {
            if (ConditionChanged != null)
                ConditionChanged(this, e);
        }
        /// <summary>
        /// Raises the <see cref="E:Collapsed"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void OnCollapsed(EventArgs e)
        {
            if (Collapsed != null)
                Collapsed(this, e);
        }
        /// <summary>
        /// Raises the <see cref="E:Expanded"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void OnExpanded(EventArgs e)
        {
            if (Expanded != null)
                Expanded(this, e);
        }
        /// <summary>
        /// Raises the <see cref="E:ToolboxControlBase.ColorsChanged"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected override void OnColorsChanged(EventArgs e)
        {
            base.OnColorsChanged(e);
        }
        /// <summary>
        /// Forces the control to re-draw when the colors are changed.
        /// </summary>
        protected override void ResetColors()
        {
            ContainerPanel.ItemBackColor = ItemBackColor;
            ContainerPanel.ItemBorderColor = ItemBorderColor;
            ContainerPanel.ItemForeColor = ItemForeColor;
            ContainerPanel.ItemHighlightBackColor = ItemHighlightBackColor;
            ContainerPanel.ItemHighlightForeColor = ItemHighlightForeColor;
            Refresh();
            OnColorsChanged(EventArgs.Empty);
        }
        /// <summary>
        /// Resizes the control based on its current visual state and raises the <b>Resize</b> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnResize(EventArgs e)
        {
            int h = base.Height;

            if ((Visible) && (Created) && (PanelTitleControl != null))
            {
                if (!_processing)
                {
                    _processing = true;
                    base.OnResize(e);
                    if (PanelTitleControl.VisualState == CollapsiblePanelState.Collapsed)
                    {
                        _expandedHeight = SuggestHeight();
                        base.Height = 16;
                        Invalidate();

                    }
                    else
                    {
                        //_expandedHeight = h;
                        base.Height = _expandedHeight;
                        Invalidate();
                        Refresh();
                        base.OnResize(e);
                    }
                    _processing = false;
                }
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Adds a new entry to the list in the container panel.
        /// </summary>
        /// <param name="newItem">
        /// The text to be displayed.
        /// </param>
        public void AddItem(string newItem)
        {
            ContainerPanel.AddItem(newItem);
            _expandedHeight = 16 + (ContainerPanel.Controls.Count * 15);
        }
        /// <summary>
        /// Adds a new entry to the list in the container panel.
        /// </summary>
        /// <param name="newItem">
        /// A <see cref="INamedInstance"/> object to add to the toolbox.
        /// </param>
        /// <remarks>
        /// When using this overload, the <b>Name</b> property of the item will be used
        /// as its ID and its display text value.
        /// </remarks>
        public void AddItem(INamedInstance newItem)
        {
            ContainerPanel.AddItem(newItem);
            _expandedHeight = 16 + (ContainerPanel.Controls.Count * 15);
        }
        /// <summary>
        /// Adds a new entry to the list in the container panel.
        /// </summary>
        /// <param name="newItem">
        /// A <see cref="NamedDisposableObjectBase"/> object to add to the toolbox.
        /// </param>
        /// <remarks>
        /// When using this overload, the <b>Name</b> property of the item will be used
        /// as its ID and its display text value.
        /// </remarks>
        public void AddItem(NamedDisposableObjectBase newItem)
        {
            ContainerPanel.AddItem(newItem);
            _expandedHeight = 16 + (ContainerPanel.Controls.Count * 15);
        }
        /// <summary>
        /// Adds a new entry to the list in the container panel.
        /// </summary>
        /// <param name="newItem">
        /// A <see cref="Control"/> object to add to the toolbox.
        /// </param>
        /// <remarks>
        /// When using this overload, the <b>Name</b> property of the item will be used
        /// as its ID and its display text value.
        /// </remarks>
        public void AddItem(Control newItem)
        {
            ContainerPanel.AddItem(newItem);
            _expandedHeight = 16 + (ContainerPanel.Controls.Count * 15);
        }
        /// <summary>
        /// Adds the range of item entries to the toolbox.
        /// </summary>
        /// <param name="itemList">
        /// A <see cref="System.Collections.Specialized.StringCollection">StringCollection</see> instance
        /// containing the list of strings to be added to the toolbox.
        /// </param>
        public void AddRange(System.Collections.Specialized.StringCollection itemList)
        {
            foreach (string item in itemList)
                AddItem(item);
        }
        /// <summary>
        /// Adds the range of item entries to the toolbox.
        /// </summary>
        /// <param name="itemList">
        /// A <see cref="Adaptive.Foundation.Collections.StringCollection">StringCollection</see> instance
        /// containing the list of strings to be added to the toolbox.
        /// </param>
        public void AddRange(Adaptive.Foundation.Collections.StringCollection itemList)
        {
            itemList.MoveFirst();
            while (!itemList.Eof)
            {
                AddItem(itemList.Value);
                itemList.MoveNext();
            }
        }
        /// <summary>
        /// Adds the range of item entries to the toolbox.
        /// </summary>
        /// <param name="itemList">
        /// A <see cref="System.Collections.Specialized.StringCollection">StringCollection</see> instance
        /// containing the list of strings to be added to the toolbox.
        /// </param>
        public void AddRange(Adaptive.Foundation.Collections.NamedDisposableObjectCollection itemList)
        {
            itemList.MoveFirst();
            while (!itemList.Eof)
            {
                AddItem(itemList.Value);
                itemList.MoveNext();
            }
        }
        /// <summary>
        /// Adds the range of item entries to the toolbox.
        /// </summary>
        /// <param name="itemList">
        /// A <see cref="System.Collections.Specialized.StringCollection">StringCollection</see> instance
        /// containing the list of strings to be added to the toolbox.
        /// </param>
        public void AddRange(string[] itemList)
        {
            foreach (string item in itemList)
                AddItem(item);
        }
        /// <summary>
        /// Adds the range of item entries to the toolbox.
        /// </summary>
        /// <param name="itemList">
        /// A <see cref="System.Collections.Specialized.StringCollection">StringCollection</see> instance
        /// containing the list of strings to be added to the toolbox.
        /// </param>
        public void AddRange(INamedInstance[] itemList)
        {
            foreach (INamedInstance item in itemList)
                AddItem(item);
        }
        /// <summary>
        /// Adds the range of item entries to the toolbox.
        /// </summary>
        /// <param name="itemList">
        /// A <see cref="System.Collections.Specialized.StringCollection">StringCollection</see> instance
        /// containing the list of strings to be added to the toolbox.
        /// </param>
        public void AddRange(Control[] itemList)
        {
            foreach (Control item in itemList)
                AddItem(item);

        }
        /// <summary>
        /// Adds the range of item entries to the toolbox.
        /// </summary>
        /// <param name="itemList">
        /// A <see cref="System.Collections.Specialized.StringCollection">StringCollection</see> instance
        /// containing the list of strings to be added to the toolbox.
        /// </param>
        public void AddRange(ControlCollection itemList)
        {
            foreach (Control item in itemList)
                AddItem(item);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Event Handlers
         *------------------------------------------------------------------------------*/
        #region Private Event Handlers
        /// <summary>
        /// Handles the event when the title bar indicates a panel expansion.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void HandleTitleExpand(object sender, EventArgs e)
        {
            ContainerPanel.Expand();
            OnResize(e);
            OnExpanded(e);
        }
        /// <summary>
        /// Handles the event when the title bar indicates a panel collapse.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void HandleTitleCollapse(object sender, EventArgs e)
        {
            ContainerPanel.Collapse();
            OnResize(e);
            OnCollapsed(e);
        }
        /// <summary>
        /// Handles the event when the title bar indicates a condition change,
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void HandleTitleConditionChange(object sender, EventArgs e)
        {
            OnConditionChanged(e);
        }
        /// <summary>
        /// Handles the control right click.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void HandleControlRightClick(object sender, EventArgs e)
        {
            OnRightClick(e);
        }
        #endregion
    }
}
